/**
*	OMaster - Cheating Tool OGame
Door: Peter Evers
Datum: 22 November 2007

  Bestand: parser.cpp
  Beschrijving:
  Dit bestand zorgt voor het parsen van de bestanden.	
**/

#include "parser.h"

// Haalt decimale punt weg, geeft pointer terug (let op! ook weer vrijgeven)
/*char *RemoveDecimal(char *text)
{
	char *szText = new char[strlen(text)+1];
	strcpy(szText, text);
	
	int i = 0;
	int found = 0;;
	for(i; i < strlen(szText); i++)
	{
		if(szText[i] == '.')
		{
			found++;
			while(szText[i+1] != '\0')
			{
				szText[i] = szText[i+1];
				i++;
			}
		}
	}
	if(found)
		szText[i-found] = '\0';
	return szText;
}*/

// Constrcutor
CParser::CParser()
{
}

// Destructor
CParser::~CParser()
{
}

/**
* Haalt de resources uit de overzicht pagina.
*
* @param		page				tekst waaruit informatie gehaald moet worden.
* @param   resources     structure die gevult gaat worden met de info.
* @return  boolean       geeft true terug als het gelukt is om de resources op te halen, anders false.
*/
bool CParser::GetResources(char *page, SResources &resources)
{
    if(page == NULL)
	{
#ifdef _DEBUG
		std::cout << "ERROR(GetResources): page == NULL" << std::endl;
#endif
        return false;
	}

	int pos = 0;
	string strTemp = page;
	string strMetaal, strKristal, strDeut;

	string strOcc = "<td align=\"center\" class=\'header\' width=\"90\"><font >";
	strTemp = strTemp.substr(strTemp.find(strOcc)+strOcc.length());
	strMetaal = strTemp.substr(0, strTemp.find('<'));
	pos = strMetaal.find('.');
	if(pos != -1)
		strMetaal.erase(strMetaal.find('.'), 1);
	resources.dMetaal = atof(strMetaal.c_str());

	strTemp = strTemp.substr(strTemp.find(strOcc)+strOcc.length());
	strKristal = strTemp.substr(0, strTemp.find('<'));
	pos = strKristal.find('.');
	if(pos != -1)
		strKristal.erase(strKristal.find('.'), 1);
	resources.dKristal = atof(strKristal.c_str());

	strTemp = strTemp.substr(strTemp.find(strOcc)+strOcc.length());
	strDeut = strTemp.substr(0, strTemp.find('<'));
	pos = strDeut.find('.');
	if(pos != -1)
		strDeut.erase(strDeut.find('.'), 1);
	resources.dDeut = atof(strDeut.c_str());

 /*   char *p = NULL;
    p = strstr(page, "id='resources'");
    if(p == NULL)
	{
#ifdef _DEBUG
		std::cout << "ERROR(LoadSession): Kan \"id='resources'\" niet vinden!" << std::endl;
#endif
        return false;
	}
    
    SkipCells(p, 2, 0);
	
	char *decimal;
	
	
	ReadNextTD(p, buffer);
	decimal = RemoveDecimal(buffer);
	resources.dMetaal = atof(decimal);
	delete[] decimal;
	delete[] buffer;
	
	ReadNextTD(p, buffer);
	decimal = RemoveDecimal(buffer);
	resources.dKristal = atof(decimal);
	delete[] decimal;
	delete[] buffer;
	
	ReadNextTD(p, buffer);
	decimal = RemoveDecimal(buffer);
	resources.dDeut = atof(decimal);
	delete[] decimal;
	delete[] buffer;*/
	
    return true;
}

/**
* Slaat aantal TR's en TD's over.
*
* @param       pSource HTML pagina
* @param       tr      aantal tr's om over te slaan
* @param       td      aantal td's om over te slaan
*/
void CParser::SkipCells(char*& pSource, int tr, int td)
{
    if(pSource == NULL)
        return;
	
    int num_tr = tr, num_td = td;
    int max_size = strlen(pSource) + 1;
    char *p = pSource, *pTemp = NULL;
    
    // Skip TR's
	while(num_tr > 0)
	{
		p = strstr(p, "<tr");
		if((p == NULL) || ((p + 3) >= &p[max_size]))
			return;
		
		p = (p + 3);
		pTemp = strstr(p, "<tr"); 
		p = strstr(p, "</tr>");   
		if(p == NULL)
			return;
		
		while((pTemp != NULL) && (strlen(p) < strlen(pTemp)))
		{
			if((pTemp + 3) >= &pTemp[max_size])
				return;
			pTemp = (pTemp + 3);   
			
			pTemp = strstr(pTemp, "</tr>");
			if(pTemp == NULL)
				return;       // Okay, er zijn geen sluit-tags gevonden
			
			if((pTemp + 5) >= &pTemp[max_size])
				return;
			pTemp = (pTemp + 5);                    
			
			p = pTemp;
			p = strstr(p, "</tr>");
			if(p == NULL)
				return;
			pTemp = strstr(pTemp, "<tr");        
		}     
		p = (p + 5);   
		num_tr--;    
	}
	
	// Skip TD's
	while(num_td > 0)
	{
		p = strstr(pSource, "<td");
		if(p == NULL)
			return;
		
		p = strstr(p, "</td>");
		if(p == NULL)
			return;
		
		num_td--;
	}
	
    pSource = p;
}

/**
* Leest de volgende TD.
*
* @param   source      lap tekst die ingelezen moet worden.
* @param   save        locatie waar inhoud wordt opgeslagen (let op! verwijder deze na gebruik)
* @return  array-lengte van blaat.
*/
int CParser::ReadNextTD(char *source, char *&save)
{
    char *temp = strstr(source, ">");
    if(temp == NULL)
        return -1;
    while(*(temp-1) == '\\')
    {
        temp = strstr(temp, ">");
        if(temp == NULL)
            return -1;
    }
    temp++;
    if(temp == NULL)
        return -1; 
    
    int len = strlen(temp) + 1;
    char *pEnd = strstr(temp, "</td>");
    if(pEnd == NULL)
        return -1;
    save = new char[len];
    int i = 0;
    while( (temp < pEnd) && (temp != NULL) && (i < len) )
    {
        save[i] = *temp;
        i++; temp++;
    }
    save[i] = '\0';
    return len;    
}


/**
* Haalt level van gebouw <building> op. // TODO: Misschien aan de hand van een optie-bestand?
*
* @param      page				tekst waar informatie uit gehaald moet worden.
* @param      building   Gebouw nummer.
* @param      language   taal-object waarin informatie over gebouwen in staat.
*/
int CParser::GetBuildingLevel(char *page, int building, ConfigFile *language, char *szLanguage)
{
	char *p = NULL;
	p = strstr(page, "<table width=\"530\">");
	if(!p)
		return -1;
	
	// zoek naar gebouw
	string strTemp = p, strBuildingCode, strBuilding;
	std::stringstream out;
	out << building;
	strBuildingCode = out.str();
	strBuilding = language->Value(szLanguage, strBuildingCode);
	strTemp = strTemp.substr(strTemp.find(strBuilding), strBuilding.length() + 20);
	int start = strTemp.find((string)language->Value(szLanguage, "Level"));
	if(start == -1) // geen level gevonden
		return 0;
	strTemp = strTemp.substr(start + ((string)language->Value(szLanguage, "Level")).length() + 1, strTemp.find(')')-1);
	return atoi(strTemp.c_str());


   /* string strTemp;
    char *p = NULL, *pTemp = NULL;
    char *buffer;   // Locatie waar resulaten in op worden geslagen   
    char szTemp[1024];
	std::stringstream out;
    
    p = strstr(page, "<table width=\"530\">");
    if(p == NULL)
        return -1;
	
    // Skip naar goede gedeelte door een TR tag over te slaan
    p = strstr(p, "<tr");
    if(p == NULL)
        return -1;
    p = p + 3;
	
    // Lees gebouw uit
    SkipCells(p, 0, 1);  
    p = p + 5;
    
    int i = 0;
    while(p != NULL)
    {
		if(ReadNextTD(p, buffer) == -1)
			break;
		p = strstr(buffer, ">");
		if(p == NULL)
		{
			delete[] buffer;
			return -1;
        }
        p++;
        pTemp = strstr(p, "</a>");
        if(pTemp == NULL)
        {
            delete[] buffer;
            return -1;
        }
        
        int i = 0;
        while(p < pTemp)
        {
            szTemp[i] = (*p++); i++;
            if(p == NULL)
            {
                delete[] buffer;
                return -1;
            }
        }
        szTemp[i] = '\0';
        
		out << building;
        strTemp = out.str();
		if((string)language->Value(szLanguage, strTemp) == szTemp)
		{    
			
			if(strstr(p, static_cast<string>(language->Value(szLanguage, "Level")).c_str()) == NULL)
			{
                delete[] buffer;
                return 0;
            }
			p = p + 7;
			int i;
			for(i = 0; *p != ' '; i++)
			{
				szTemp[i] = *(p++);       
                if(p = NULL)
                {
					delete[] buffer;
					return -1;
                }         
			}    
			szTemp[i] = '\0';
			int level = atoi(szTemp);
			delete[] buffer;
			return level;
		}
		else
		{
			SkipCells(p, 0, (++i * 3));
		}
        delete[] buffer;
    } 
    return -1;*/
}

/**
* Haalt sessie uit de pagina, dit gaat aan de hand door op zoek te gaan naar 'session='
*
* @param		page	bulk tekst waar informatie uit gehaald moet worden.
* @return	sessie, als er niks gevonden wordt, wordt er NULL terug gegeven.
*/
char *CParser::GetSession(char *page)
{
	char *p = NULL, szTemp[256];
	p = strstr(page, "session=");
	if(p == NULL)
		return NULL;
	p = p + 8;	// Skip naar sessie
	
	int i = 0;
	while((p[i] != '&') || (p == NULL))
	{
		szTemp[i] = p[i];
		i++;
	}
	if(p[i] == '&')
		szTemp[i] = '\0';
	else
		return NULL;
	return szTemp;
}

/**
* Haalt planeten uit pagina, stopt ze vervolgens in de vector.
*
* @param		page	bulk tekst waar informatie uit gehaald moet worden, zoals gewoonlijk ;-).
* @param		planets	pointer naar vector van SPlanet waarin de planeten komen te staan.
* @return	Aantal planeten van speler, bij een fout -1
*/
int CParser::GetPlanets(char *page, vector<SPlanet> &planets)
{
	char *p = NULL, *pTemp = NULL, *pEnd = NULL;
	SPlanet planet;
	
	p = strstr(page, "<option value=\"/game/index.php");
	if(p == NULL) return -1;
	pEnd = strstr(page, "</select>");
	if(pEnd == NULL)
		return -1;
	
	p = strstr(p, "cp=");
	if(p == NULL) return -1;
	
	int numplanets = 0;
	while(p < pEnd)
	{
		// Zoek id
		p = p + 3;
		pTemp = strstr(p, "&");
		planet.id.assign(p, strlen(p) - strlen(pTemp));
		
		
		// Zoek naam
		p = strstr(p, ">");
		if(p == NULL)
			return -1;
		p = p + 1;
		
		pTemp = strstr(p, "\t");
		planet.name.assign(p, strlen(p) - strlen(pTemp));
		
		planets.push_back(planet);
		p = strstr(p, "cp=");
		if(p == NULL)
			p = pEnd;
		numplanets++;
	}
	return numplanets;
}


// Secret Message: KORN ROCKS!
